/*
    Copyright (c) 2021 Shanghai Macrogiga Electronics Co., Ltd.

    Permission is hereby granted, free of charge, to any person 
    obtaining a copy of this software and associated documentation 
    files (the "Software"), to deal in the Software without 
    restriction, including without limitation the rights to use, copy, 
    modify, merge, publish, distribute, sublicense, and/or sell copies 
    of the Software, and to permit persons to whom the Software is 
    furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be 
    included in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
    DEALINGS IN THE SOFTWARE.
*/
#include "BSP.h"
#include "mg_api.h"

static SPI_HandleTypeDef spi_test = {0};
static LPTIM_HandleTypeDef sLpTimHandle = {0};

static unsigned char *ble_mac_addr0;

////MS1656 internal resource related, DONOT change this file////
//IRQ - PB4
//CSN - PC4
//SCK - PC5
//MOSI - PC6
//MISO - PD2

unsigned char SPI_WriteRead(unsigned char SendData,unsigned char WriteFlag)
{
    spi_test.Instance->DATA = SendData;
    while(0 == (spi_test.Instance->SR & SPI_SR_SPIF));
    return spi_test.Instance->DATA;
}

void SPI_CS_Enable_(void)
{
    HAL_GPIO_WritePin(SPI_NSS_GPIO,SPI_NSS_PIN,GPIO_PIN_RESET);
}

void SPI_CS_Disable_(void)
{
    HAL_GPIO_WritePin(SPI_NSS_GPIO,SPI_NSS_PIN,GPIO_PIN_SET);
}

static unsigned char Tab[33];
unsigned char SPI_WriteBuf(unsigned char reg, unsigned char const *pBuf, unsigned char len)
{
    SPI_CS_Enable_();
    Tab[0] = reg;
    memcpy(Tab+1,pBuf,len);
    LL_SPI_Master_TransmitReceive(&spi_test,Tab,len+1,NULL,0);
    SPI_CS_Disable_();
    return 0;
}
unsigned char SPI_ReadBuf(unsigned char reg, unsigned char *pBuf, unsigned char len)
{
    unsigned char Temp;
    
    SPI_CS_Enable_();
    Temp = reg;
    LL_SPI_Master_TransmitReceive(&spi_test,&Temp,1,Tab,len);
    memcpy(pBuf,Tab,len);
    SPI_CS_Disable_();
    return 0;
}
/**
  * @brief HAL_SPI_MspInit Configuration
  * @retval None
  */
void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
{
    __HAL_RCC_GPIOD_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_SPI_CLK_ENABLE();
    
    GPIO_InitTypeDef  gpiospi={0};
    /* Configure the GPIO_NSS pin */
    gpiospi.Pin    = SPI_NSS_PIN ;
    gpiospi.Mode = GPIO_MODE_OUTPUT;
    gpiospi.OpenDrain = GPIO_PUSHPULL;
    gpiospi.Debounce.Enable = GPIO_DEBOUNCE_DISABLE;
    gpiospi.SlewRate = GPIO_SLEW_RATE_LOW;
    gpiospi.DrvStrength = GPIO_DRV_STRENGTH_HIGH;
    gpiospi.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(SPI_NSS_GPIO, &gpiospi);
    
    SPI_CS_Disable_();
    
    /* Configure the MOSI pin */
    gpiospi.Pin    = SPI_MOSI_PIN ;
    gpiospi.Mode = GPIO_MODE_AF;
    gpiospi.Alternate = GPIO_AF3_SPI_MOSI;
    gpiospi.OpenDrain = GPIO_PUSHPULL;
    gpiospi.Debounce.Enable = GPIO_DEBOUNCE_DISABLE;
    gpiospi.SlewRate = GPIO_SLEW_RATE_HIGH;
    gpiospi.DrvStrength = GPIO_DRV_STRENGTH_HIGH;
    gpiospi.Pull = GPIO_NOPULL;
    
    HAL_GPIO_Init(SPI_MOSI_GPIO, &gpiospi);
    HAL_GPIO_WritePin(SPI_MOSI_GPIO, SPI_MOSI_PIN, GPIO_PIN_SET);
    /* Configure the MISO pin */
    gpiospi.Pin    = SPI_MISO_PIN ;
    gpiospi.Mode = GPIO_MODE_AF;
    gpiospi.Alternate = GPIO_AF3_SPI_MISO;
    gpiospi.OpenDrain = GPIO_PUSHPULL;//GPIO_OPENDRAIN
    gpiospi.Debounce.Enable = GPIO_DEBOUNCE_DISABLE;
    gpiospi.SlewRate = GPIO_SLEW_RATE_HIGH;//GPIO_SLEW_RATE_LOW;
    gpiospi.DrvStrength = GPIO_DRV_STRENGTH_LOW;
    gpiospi.Pull = GPIO_NOPULL;
    
    HAL_GPIO_Init(SPI_MISO_GPIO, &gpiospi);
    //HAL_GPIO_WritePin(SPI_MOSI_GPIO, SPI_MOSI_PIN, SET);
    /* Configure the CLK pin */
    gpiospi.Pin    = SPI_CLK_PIN ;
    gpiospi.Mode = GPIO_MODE_AF;
    gpiospi.Alternate = GPIO_AF3_SPI_CLK;
    gpiospi.OpenDrain = GPIO_PUSHPULL;//GPIO_OPENDRAIN;//GPIO_PUSHPULL;
    gpiospi.Debounce.Enable = GPIO_DEBOUNCE_DISABLE;
    gpiospi.SlewRate = GPIO_SLEW_RATE_HIGH;//GPIO_SLEW_RATE_LOW;
    gpiospi.DrvStrength = GPIO_DRV_STRENGTH_HIGH;
    gpiospi.Pull = GPIO_PULLDOWN;//GPIO_NOPULL;
    
    HAL_GPIO_Init(SPI_CLK_GPIO, &gpiospi);
}

void SPIM_Init(void)
{
    spi_test.Instance = SPI;
    spi_test.Init.NSS = SPI_NSS_MODE_HIGH;
    spi_test.Init.Mode = SPI_MODE_MASTER;
    spi_test.Init.CLKPhase = SPI_POLARITY_LOW;
    spi_test.Init.CLKPolarity = SPI_PHASE_1EDGE;
    spi_test.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
    HAL_SPI_Init(&spi_test);
}

static unsigned char TimeOut = 0;
void LPTIM_TimeOut_Reset(void)
{
    TimeOut = 0;
}
/**
  * @brief This function handles LPTIM Interrupt .
  */
void LPTIM_IRQHandler(void)
{
    if(__HAL_LPTIM_GET_FLAG(&sLpTimHandle) != RESET)
    {
        if(__HAL_LPTIM_GET_IT_SOURCE(&sLpTimHandle) !=RESET)
        {
            __HAL_BASETIM_CLEAR_IT(&sLpTimHandle);
            if (3 == TimeOut)
            {
#ifdef MS1658_BOARD
                HAL_NVIC_DisableIRQ(GPIOD_IRQn);
#else
                HAL_NVIC_DisableIRQ(GPIOB_IRQn);
#endif
                radio_initBle(TXPWR_0DBM, &ble_mac_addr0);
#ifdef MS1658_BOARD
                HAL_NVIC_EnableIRQ(GPIOD_IRQn);
#else
                HAL_NVIC_EnableIRQ(GPIOB_IRQn);
#endif
                ble_run_interrupt_start(0);
            }
            TimeOut++;
        }
    }
}

void LPTIM_Init(unsigned short period)
{
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};	

    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LIRC;
    RCC_OscInitStruct.LIRCState = RCC_LIRC_ON;
    RCC_OscInitStruct.LIRCCalibrationValue = RCC_LIRCCALIBRATION_38K;
    
    if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    {
        Error_Handler();
    }
    
    __HAL_RCC_LPTIM_CLK_ENABLE();

    sLpTimHandle.Instance = LPTIM;	
    sLpTimHandle.Init.ClkSel = LPTIM_CLOCK_SOURCE_LIRC;
    sLpTimHandle.Init.CntTimSel = LPTIM_TIMER_SELECT;
    sLpTimHandle.Init.AutoReload = LPTIM_AUTORELOAD_ENABLE;
    sLpTimHandle.Init.Period = 0xffff - period;
    HAL_LPTIM_Base_Init(&sLpTimHandle);

    HAL_LPTIM_Base_Start_IT(&sLpTimHandle);
    HAL_NVIC_SetPriority(LPTIM_IRQn, PRIORITY_LOWEST);
    HAL_NVIC_EnableIRQ(LPTIM_IRQn);
}

char IsIrqEnabled(void)
{
    return (!HAL_GPIO_ReadPin(IRQ_GPIO,IRQ_PIN));
}


void McuGotoSleepAndWakeup(void)
{
}
void SysClk8to48(void)
{
}
void SysClk48to8(void)
{
}
void DisableEnvINT(void)
{
}
void EnableEnvINT(void)
{
}
void UpdateLEDValueAll(void)
{
}
